
#include <BFont>
#include <BApplication>
#include "member_BFont.h"

using namespace BWE;

#define member					(*(member_BFont*)_ptr)
#define member_allocate()		_ptr = new member_BFont(this)
#define member_release()		delete (member_BFont*)_ptr

BFont::BFont(const BSize& size)
{
	member_allocate();
	member.size = size;
}
BFont::BFont(const BString& family, const BSize& size)
{
	member_allocate();
	member.size = size;
	setFamily(family);
}
BFont::~BFont()
{
	member_release();
}

void BFont::setFamily(const BString& family)
{
	BString realFamily;
	if (family.contain('/') || family.contain('.'))
	{
		int begin = family.rfind('/') + 1;
		int end = family.rfind('.');
		if (begin < end)
		{
			realFamily = family.substr(begin, end);
		}
		if (begin > 0)
		{
			BApplication::addFontPath(family.substr(0, begin));
		}
	}
	else
	{
		realFamily = family;
	}

	if (member.family != realFamily)
	{
		member.family = realFamily;
		member.loadFamily();
	}
}
const BString& BFont::family() const
{
	return member.family;
}

void BFont::setBold(bool bold)
{
	member.bold = bold;
}
bool BFont::bold() const
{
	return member.bold;
}

void BFont::setItalic(bool italic)
{
	member.italic = italic;
}
bool BFont::italic() const
{
	return member.italic;
}

void BFont::setUnderline(bool underline)
{
	member.underline = underline;
}
bool BFont::underline() const
{
	return member.underline;
}

void BFont::setSpaceSize(int spaceSize)
{
	member.spaceSize = spaceSize;
}
int BFont::spaceSize() const
{
	return member.spaceSize;
}

void BFont::setTabSize(int tabSize)
{
	member.tabSize = tabSize;
}
int BFont::tabSize() const
{
	return member.tabSize;
}

bool BFont::setEncoding(Encoding encoding)
{
	if (member.fontFamily && member.encoding != encoding)
	{
		member.encoding = encoding;
		if (member.fontFamily->changeEncoding(encoding))
		{
			member.table.clear();
			return true;
		}
		return false;
	}
	return true;
}
Encoding BFont::encoding(int index) const
{
	if (!member.fontFamily)
		return Encoding_None;
	return member.fontFamily->encodingList(index);
}
int BFont::encodingCount() const
{
	if (member.fontFamily)
		return member.fontFamily->encodingList.size();
	return 0;
}

void BFont::setBitmap(BCode code, BImage* bitmap)
{
	member.troubleCodes.remove(code);
	CodeInfo& info = member.table[code];
	info.bitmap = bitmap;
}
BImage* BFont::bitmap(BCode code)
{
	CodeInfo* info = member.getCodeInfo(code);
	if(info)
		return info->bitmap.ptr();
	return 0;
}
const BImage* BFont::bitmap(BCode code) const
{
	CodeInfo* info = member.getCodeInfo(code);
	if (info)
		return info->bitmap.ptr();
	return 0;
}

void BFont::setGlyph(BCode code, BGlyph* glyph)
{
	member.troubleCodes.remove(code);
	CodeInfo& info = member.table[code];
	info.glyph = glyph;
}
BGlyph* BFont::glyph(BCode code)
{
	CodeInfo* info = member.getCodeInfo(code);
	if (info)
		return info->glyph.ptr();
	return 0;
}
const BGlyph* BFont::glyph(BCode code) const
{
	CodeInfo* info = member.getCodeInfo(code);
	if (info)
		return info->glyph.ptr();
	return 0;
}

void BFont::setSize(const BSize& size)
{
	if (member.size != size)
	{
		member.size = size;
		member.table.clear();
	}
}
void BFont::setSize(int width, int height)
{
	member.size.set(width, height);
}
const BSize& BFont::size() const
{
	return member.size;
}

void BFont::setWidth(int width)
{
	member.size.setWidth(width);
}
int BFont::width() const
{
	return member.size.width();
}

void BFont::setHeight(int height)
{
	member.size.setHeight(height);
}
int BFont::height() const
{
	return member.size.height();
}

BSize BFont::codeSize(BCode code) const
{
	return member.codeSize(code);
}
int BFont::codeWidth(BCode code) const
{
	return member.codeSize(code).width();
}
int BFont::codeHeight(BCode code) const
{
	return member.codeSize(code).height();
}

BSize BFont::textSize(const BString& text) const
{
	int x = 0;
	int y = 0;
	int totalWidth = 0;
	int totalHeight = member.size.height();
	for (BString::const_iterator it = text.begin(); it != text.end(); it++)
	{
		BCode code = it.value();
		if (code == '\n')//new line.
		{
			x = x;
			totalHeight += member.size.height();
		}
		if (code == '\t')
		{
			int times = x / member.size.width() + 1;
			x = times * member.size.width() + x;
		}
		BSize codeSize = member.codeSize(code);
		x += codeSize.width();
		if (totalWidth < x)
			totalWidth = x;
	}
	return BSize(totalWidth, totalHeight);
}

